﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Xml;
using Huinn.Common.XML;
using System.Linq;
using System.Data.Objects;
using System.Collections.Generic;

namespace Huinn.AirQuality
{
    public class AirQualityIndex
    {
        private const string COM_PM25_IN_PUBLIC_APP_KEY = "5j1znBVAsnSf5xQyNQyq";
        private const string COM_PM25_IN_PM2_5_URL = "http://www.pm25.in/api/querys/pm2_5.json";

        private const string COM_PM25_IN_GET_ALL_CITY_AIR_QUALITY_URL = "http://www.pm25.in/api/querys/all_cities.json";

        public string GetAllCitiesAirQualityData(out bool isOutOfService)
        {
            isOutOfService = false;
            string responseBody = string.Empty;

            string requestUrl = string.Format("{0}?token={1}", COM_PM25_IN_GET_ALL_CITY_AIR_QUALITY_URL, COM_PM25_IN_PUBLIC_APP_KEY);
            responseBody = GetHttpWebResponseBodyByHttpRequestUrl(requestUrl);

            // Possible errors:
            // "error": "参数不能为空"
            // "error": "该城市还未有PM2.5数据"
            // "error": "Sorry，您这个小时内的API请求次数用完了，休息一下吧！"
            // "error": "You need to sign in or sign up before continuing."
            if (responseBody.Contains("error"))
            {
                isOutOfService = true;
            }
            return responseBody;
        }

        public void AllCitiesAirQualityDataStorage(string allCitiesAirQualityDataJson)
        {
            System.Web.Script.Serialization.JavaScriptSerializer JSS = new System.Web.Script.Serialization.JavaScriptSerializer();
            object deserializedData = JSS.DeserializeObject(allCitiesAirQualityDataJson);

            using (Huinn.Data.Entities.HuinnDBEntities db = new Data.Entities.HuinnDBEntities())
            {
                #region Position Air Quality Analysis
                foreach (var item in (object[])deserializedData)
                {
                    Huinn.Data.Entities.PositionAirQuality positionAirQuality = new Data.Entities.PositionAirQuality();
                    foreach (var element in (Dictionary<string, object>)item)
                    {
                        switch (element.Key)
                        {
                            case "aqi": positionAirQuality.AQI = element.Value.ToString(); break;
                            case "area": positionAirQuality.CityName = element.Value.ToString(); break;
                            case "co": positionAirQuality.CO = element.Value.ToString(); break;
                            case "co_24h": positionAirQuality.CO_24h = element.Value.ToString(); break;
                            case "no2": positionAirQuality.NO2 = element.Value.ToString(); break;
                            case "no2_24h": positionAirQuality.NO2_24h = element.Value.ToString(); break;
                            case "o3": positionAirQuality.O3 = element.Value.ToString(); break;
                            case "o3_24h": positionAirQuality.O3_24h = element.Value.ToString(); break;
                            case "o3_8h": positionAirQuality.O3_8h = element.Value.ToString(); break;
                            case "o3_8h_24h": positionAirQuality.O3_8h_24h = element.Value.ToString(); break;
                            case "pm10": positionAirQuality.PM10 = element.Value.ToString(); break;
                            case "pm10_24h": positionAirQuality.PM10_24h = element.Value.ToString(); break;
                            case "pm2_5": positionAirQuality.PM25 = element.Value.ToString(); break;
                            case "pm2_5_24h": positionAirQuality.PM25_24h = element.Value.ToString(); break;
                            case "position_name": positionAirQuality.PositionName = element.Value.ToString(); break;
                            case "primary_pollutant": positionAirQuality.PrimaryPollutant = element.Value.ToString(); break;
                            case "quality": positionAirQuality.Quality = element.Value.ToString(); break;
                            case "so2": positionAirQuality.SO2 = element.Value.ToString(); break;
                            case "so2_24h": positionAirQuality.SO2_24h = element.Value.ToString(); break;
                            case "station_code": positionAirQuality.StationCode = element.Value.ToString(); break;
                            case "time_point": positionAirQuality.UpdatedTime = element.Value.ToString(); break;
                        }
                    }
                    db.SaveChanges();
                }
                #endregion
            }

        }

        public string GetPM25JsonByCityCode(string cityCode, out bool isOutOfService)
        {
            isOutOfService = false;
            string responseBody = string.Empty;
            string requestUrl = string.Format("{0}?city={1}&token={2}&&stations=no", COM_PM25_IN_PM2_5_URL, cityCode, COM_PM25_IN_PUBLIC_APP_KEY);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader streamReader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8))
            {
                responseBody = streamReader.ReadToEnd();
            }
            response.Close();
            if (responseBody.Contains("error"))
            {
                isOutOfService = true;
            }
            return responseBody;
        }

        public XmlDocument ConvertJsonToXml(string pm25Json)
        {
            System.Web.Script.Serialization.JavaScriptSerializer JSS = new System.Web.Script.Serialization.JavaScriptSerializer();
            object deserializedData = JSS.DeserializeObject(pm25Json);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("<PM25_Data>");
            foreach (var item in (object[])deserializedData)
            {
                foreach (var element in (Dictionary<string, object>)item)
                {
                    if (element.Key == "area")
                    {
                        stringBuilder.Append(string.Format("<Area>{0}</Area>", element.Value.ToString()));
                        continue;
                    }
                    else if (element.Key == "aqi")
                    {
                        stringBuilder.Append(string.Format("<Aqi>{0}</Aqi>", element.Value.ToString()));
                        continue;
                    }
                    else if (element.Key == "pm2_5")
                    {
                        stringBuilder.Append(string.Format("<PM25>{0}</PM25>", element.Value.ToString()));
                        continue;
                    }
                    else if (element.Key == "pm2_5_24h")
                    {
                        stringBuilder.Append(string.Format("<PM25_24h>{0}</PM25_24h>", element.Value.ToString()));
                        continue;
                    }
                    else if (element.Key == "quality")
                    {
                        stringBuilder.Append(string.Format("<Quality>{0}</Quality>", element.Value.ToString()));
                        continue;
                    }
                    else if (element.Key == "time_point")
                    {
                        stringBuilder.Append(string.Format("<Updated>{0}</Updated>", element.Value.ToString()));
                        continue;
                    }
                }
            }
            stringBuilder.Append("</PM25_Data>");
            XmlDocument pm25XmlDocument = new XmlDocument();
            XmlElement root = XmlHelper.InitializeXml(pm25XmlDocument, "Huinn");
            root.InnerXml = stringBuilder.ToString();
            return pm25XmlDocument;
        }

        public string GetHttpWebResponseBodyByHttpRequestUrl(string requestUrl)
        {
            string responseBody = string.Empty;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader streamReader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8))
            {
                responseBody = streamReader.ReadToEnd();
            }
            response.Close();
            return responseBody;
        }

        // get city air quality by city name (chinese), such as 北京、重庆, with keywords: 空气质量
        // for eaxmple, try get beijing's air quality index, user should input this string: 北京空气质量
        // I think, we should create 2 tables, one for data storage, one for audit
        // we get lastest data from data table,
        // so far, we only return aqi data to analyse air quality, because of China's air quality by the air pollution index evaluation
        //
        // 目前，城市空气质量污染指数的分级标准是：
        // ①（AQI）0～50，为国家空气质量日均值一级标准，空气质量为优，符合自然保护区、风景名胜区和其他需要特殊保护地区的空气质量要求。
        // ②（AQI）51～100，为国家空气质量日均值二级标准，空气质量良好，符合居住区、商业区、文化区、一般工业区和农村地区空气质量的要求。
        // ③（AQI）101～200，为三级标准，空气质量为轻度污染。若长期接触本级空气，易感人群病状会轻度加剧，健康人群出现刺激症状。符合特定工业区的空气质量要求。
        // ④（AQI）201～300，为四级标准,窄气质量为中度污染。接触本级空气一定时间后，心脏病和肺病患者症状显著加剧，运动耐受力降低，健康人群中普遍出现症状。
        // ⑤（AQI）大于300，为五级标准，空气质量为重度污染。健康人运动耐受力降低，有明显症状并出现某些疾病。
        public static int GetCityAqiByCityName(string cityName)
        {
            int aqiSum = 0;
            int aqiPositionCount = 0;
            using (Huinn.Data.Entities.HuinnDBEntities db = new Data.Entities.HuinnDBEntities())
            {
                var query = from record in db.PositionAirQualities
                            where record.CityName == cityName
                            select record;

                foreach (var item in query)
                {
                    if (string.Compare(item.AQI, "0") != 0) //PositionAirQualities AQI should be int type, I'll update this issue
                    {
                        aqiSum += Convert.ToInt32(item.AQI);
                        aqiPositionCount++;
                    }
                }
            }
            return aqiSum / aqiPositionCount;
        }

        public static string GetCityAirQualityLevelByCityAqi(int aqi)
        {
            if (aqi < 50)
                return "优";
            if (aqi < 100)
                return "良好";
            if (aqi < 200)
                return "轻度污染";
            if (aqi < 300)
                return "中度污染";
            return "重度污染";
        }
    }

    //public class PositionAirQuality
    //{
    //    public string CityName;
    //    public string AQI;
    //    public string CO;
    //    public string CO_24h;
    //    public string NO2;
    //    public string NO2_24h;
    //    public string O3;
    //    public string O3_24h;
    //    public string O3_8h;
    //    public string O3_8h_24h;
    //    public string PM10;
    //    public string PM10_24h;
    //    public string PM25;
    //    public string PM25_24h;
    //    public string PositionName;
    //    public string PrimaryPollutant;
    //    public string Quality;
    //    public string SO2;
    //    public string SO2_24h;
    //    public string StationCode;
    //    public string UpdatedTime;
    //}
}
